package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"log"
	"net/http"
	"os"
	"path/filepath"
	"strings"
	"time"
)

var Data []Video
var Root string

type Video struct {
	Id       int     `json:"id"`
	Label    string  `json:"label"`
	Path     string  `json:"path"`
	Children []Video `json:"children"`
}

func Go(root string) {
	Data = []Video{}
	err := filepath.Walk(root, findTxtDir)
	log.Println(err)
	fmt.Println(Data)
}

func WatchDog(root string) {
	timeTicker := time.NewTicker(30 * time.Second)
	Go(root)
	for _ = range timeTicker.C {
		Go(root)
	}
}

// 找出目录下所有mp4|avi
// WalkFunc 函数：
// 列出含有 *.txt 文件的目录（不是全部，因为会跳过一些子目录）
func findTxtDir(path string, info os.FileInfo, err error) error {
	ok, err := filepath.Match(`*.mp4`, info.Name())
	if ok {
		fmt.Println(filepath.Dir(path), path, info.Name())
		// 遇到 txt 文件则继续处理所在目录的下一个目录
		// 注意会跳过子目录
		tmp := Video{
			Id:    time.Now().Nanosecond(),
			Label: info.Name(),
			Path:  strings.Replace(path, Root, "", 1),
		}
		Data = append(Data, tmp)
		// return filepath.SkipDir
	}
	ok, err = filepath.Match(`*.avi`, info.Name())
	if ok {
		fmt.Println(filepath.Dir(path), info.Name())
		// 遇到 txt 文件则继续处理所在目录的下一个目录
		// 注意会跳过子目录
		tmp := Video{
			Id:    time.Now().Nanosecond(),
			Label: info.Name(),
			Path:  strings.Replace(path, Root, "", 1),
		}
		Data = append(Data, tmp)
		// return filepath.SkipDir
	}
	return err
}

// WalkFunc 函数：
// 列出所有以 ab 开头的目录（全部，因为没有跳过任何项目）
func findabDir(path string, info os.FileInfo, err error) error {
	if info.IsDir() {
		ok, err := filepath.Match(`[aA][bB]*`, info.Name())
		if err != nil {
			return err
		}
		if ok {
			fmt.Println(path)
		}
	}
	return nil
}

func GetPathJson(w http.ResponseWriter, req *http.Request) {
	if origin := req.Header.Get("Origin"); origin != "" {
		w.Header().Add("Access-Control-Allow-Origin", "*")
		w.Header().Add("Access-Control-Allow-Methods", "DELETE, POST, GET, PUT, OPTIONS")
		// 关键bug 需要允许client header提交的字段 比如这次出现的Authorization
		w.Header().Add("Access-Control-Allow-Headers", "Content-Type,Authorization,X-Token")
		// w.Header().Add("Access-Control-Allow-Headers", "Content-Type,Action, Module")
		w.Header().Add("Access-Control-Allow-Credentials", "true")
		w.Header().Add("Access-Control-Max-Age", "1728000")
		w.Header().Add("content-type", "application/json")
	}

	if req.Method == "OPTIONS" {
		return
	}

	info, err := json.Marshal(Data)
	if err != nil {
		fmt.Fprintf(w, err.Error())
	} else {
		w.Write(info)
	}
}

func main() {
	var port string
	flag.StringVar(&Root, "path", "/tmp", "视频文件路径")
	flag.StringVar(&port, "port", "8080", "服务器端口")

	flag.Parse()

	log.Println("开始扫描 " + Root + " 目录视频文件......")
	Data = []Video{}
	go func() {
		WatchDog(Root)
	}()

	log.Println(fmt.Sprintf("端口: %s", port))
	log.Println(fmt.Sprintf("路径: %s", Root))
	log.Println(fmt.Sprintf("服务器开始监听 %s ......", port))

	changeHeaderThenServe := func(h http.Handler) http.HandlerFunc {
		return func(w http.ResponseWriter, r *http.Request) {
			// Set some header.
			// w.Header().Add("Keep-Alive", "300")
			w.Header().Add("Access-Control-Allow-Origin", "*")
			w.Header().Add("Access-Control-Allow-Methods", "DELETE, POST, GET, PUT, OPTIONS")
			w.Header().Add("Access-Control-Allow-Headers", "Content-Type,Authorization,X-Token")
			w.Header().Add("Access-Control-Allow-Credentials", "true")
			w.Header().Add("Access-Control-Max-Age", "1728000")
			// w.Header().Add("content-type", "application/json")
			// Serve with the actual handler.
			h.ServeHTTP(w, r)
		}
	}

	http.HandleFunc("/json", GetPathJson)
	http.Handle("/", changeHeaderThenServe(http.FileServer(http.Dir(Root))))
	err := http.ListenAndServe(fmt.Sprintf(":%s", port), nil)
	if err != nil {
		panic(err)
	}
}
